/*
* Copyright (C) 2019 ~ 2021 Uniontech Software Technology Co.,Ltd.
*
* Author:     yanghongwei <yanghongwei@uniontech.com>
*
* Maintainer: yanghongwei <yanghongwei@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "tuogun_product_device.h"
#include "mysql_session.h"

#include <Poco/DateTimeFormatter.h>
#include <Poco/Data/Session.h>
#include <Poco/Exception.h>

#include <plog/Log.h>

using namespace Poco::Data;
using namespace Poco::Data::Keywords;

namespace Poco
{
    namespace Data
    {
        template<>
        class TypeHandler<struct TuogunProductDevice>
        {
        public:
            static void bind(std::size_t pos, const TuogunProductDevice &obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir) {
                // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))
                // Note that we advance pos by the number of columns the datatype uses! For string/int this is one.
                poco_assert_dbg (!pBinder.isNull());
                TypeHandler<uint32_t>::bind(pos++, obj.id, pBinder, dir);
                TypeHandler<uint32_t>::bind(pos++, obj.product_line_id, pBinder, dir);
                TypeHandler<uint32_t>::bind(pos++, obj.device_id, pBinder, dir);
                TypeHandler<std::string>::bind(pos++, obj.device_name, pBinder, dir);
                TypeHandler<uint8_t>::bind(pos++, obj.is_enable, pBinder, dir);
                TypeHandler<uint32_t>::bind(pos++, obj.seq_no, pBinder, dir);
                TypeHandler<Poco::DateTime>::bind(pos++, obj.create_time, pBinder, dir);
                TypeHandler<Poco::DateTime>::bind(pos++, obj.update_time, pBinder, dir);
            }
            static void extract(std::size_t pos, TuogunProductDevice &obj, const TuogunProductDevice &defVal, AbstractExtractor::Ptr pExt) {
                // defVal is the default person we should use if we encunter NULL entries, so we take the individual fields
                // as defaults. You can do more complex checking, ie return defVal if only one single entry of the fields is null etc...
                poco_assert_dbg (!pExt.isNull());
                // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))
                TypeHandler<uint32_t>::extract(pos++, obj.id, defVal.id, pExt);
                TypeHandler<uint32_t>::extract(pos++, obj.product_line_id, defVal.product_line_id, pExt);
                TypeHandler<uint32_t>::extract(pos++, obj.device_id, defVal.device_id, pExt);
                TypeHandler<std::string>::extract(pos++, obj.device_name, defVal.device_name, pExt);
                TypeHandler<uint8_t>::extract(pos++, obj.is_enable, defVal.is_enable, pExt);
                TypeHandler<uint32_t>::extract(pos++, obj.seq_no, defVal.seq_no, pExt);
                TypeHandler<Poco::DateTime>::extract(pos++, obj.create_time, defVal.create_time, pExt);
                TypeHandler<Poco::DateTime>::extract(pos++, obj.update_time, defVal.update_time, pExt);
            }
            static void prepare(std::size_t pos, const TuogunProductDevice &obj, AbstractPreparator::Ptr pPreparator) {
                // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))
                poco_assert_dbg (!pPreparator.isNull());
                TypeHandler<uint32_t>::prepare(pos++, obj.id, pPreparator);
                TypeHandler<uint32_t>::prepare(pos++, obj.product_line_id, pPreparator);
                TypeHandler<uint32_t>::prepare(pos++, obj.device_id, pPreparator);
                TypeHandler<std::string>::prepare(pos++, obj.device_name, pPreparator);
                TypeHandler<uint8_t>::prepare(pos++, obj.is_enable, pPreparator);
                TypeHandler<uint32_t>::prepare(pos++, obj.seq_no, pPreparator);
                TypeHandler<Poco::DateTime>::prepare(pos++, obj.create_time, pPreparator);
                TypeHandler<Poco::DateTime>::prepare(pos++, obj.update_time, pPreparator);
            }
            static std::size_t size() { return 8; }
        };
    }
}

void printf(const TuogunProductDevice &device)
{
    LOGD << "TuogunProductDevice[id:" << device.id << " "
            << "product_line_id:" << device.product_line_id << " "
            << "device_id:" << device.device_id << " "
            << "device_name:" << device.device_name << " "
            << "is_enable:" << (int32_t)device.is_enable << " "
            << "seq_no:" << device.seq_no << " "
            << "create_time:" << Poco::DateTimeFormatter::format(device.create_time, Poco::DateTimeFormat::ISO8601_FORMAT) << " "
            << "update_time:" << Poco::DateTimeFormatter::format(device.update_time, Poco::DateTimeFormat::ISO8601_FORMAT) << "]";
}

std::vector<TuogunProductDevice> TuogunProductDeviceManager::getTuogunProductDeviceByProductLine(uint32_t product_line_id)
{
    std::vector<TuogunProductDevice> ver_device;
    try {
        if (MysqlSession::Instance()->session()) {
            Statement query(*MysqlSession::Instance()->session());
            query << "SELECT * FROM tuogun_product_device WHERE product_line_id=?",use(product_line_id),into(ver_device),now;
        }
    } catch (Poco::Exception &e) {
        LOGW << "exception : " << e.what();
    }
    return ver_device;
}

std::vector<TuogunProductDevice> TuogunProductDeviceManager::getTuogunProductDeviceBySelective(TuogunProductDevice record)
{
    std::vector<TuogunProductDevice> ver_device;
    try {
        if (MysqlSession::Instance()->session()) {
            printf(record);
            Statement query(*MysqlSession::Instance()->session());
            query << "SELECT * FROM tuogun_product_device where product_line_id=? and device_id=? and device_name=? and \
                    is_enable=? and seq_no=?",
                    use(record.product_line_id),use(record.device_id),use(record.device_name),use(record.is_enable),
                    use(record.seq_no),into(ver_device),now;
        }
    } catch (Poco::Exception &e) {
        LOGW << "exception : " << e.what();
    }
    return ver_device;
}

std::vector<TuogunProductDevice> TuogunProductDeviceManager::getTuogunProductDeviceBySelective(uint32_t product_line_id, std::string device_name)
{
    std::vector<TuogunProductDevice> ver_device;
    try {
        if (MysqlSession::Instance()->session()) {
            Statement query(*MysqlSession::Instance()->session());
            query << "SELECT * FROM tuogun_product_device where product_line_id=? and device_name=?",
                    use(product_line_id),use(device_name),into(ver_device),now;
        }
    } catch (Poco::Exception &e) {
        LOGW << "exception : " << e.what();
    }
    return ver_device;
}

TuogunProductDevice TuogunProductDeviceManager::getTuogunProductDeviceByProductAndName(uint32_t product_line_id, std::string device_name)
{
    TuogunProductDevice device;
    try {
        if (MysqlSession::Instance()->session()) {
            Statement query(*MysqlSession::Instance()->session());
            query << "SELECT * FROM tuogun_product_device WHERE product_line_id=? and device_name=? limit 1",
                    use(product_line_id),use(device_name),into(device),now;
        }
    } catch (Poco::Exception &e) {
        LOGW << "exception : " << e.what();
    }
    return device;
}

TuogunProductDevice TuogunProductDeviceManager::getTuogunProductDeviceByDeviceId(uint32_t deviceId)
{
    TuogunProductDevice device;
    try {
        if (MysqlSession::Instance()->session()) {
            Statement query(*MysqlSession::Instance()->session());
            query << "SELECT * FROM tuogun_product_device WHERE device_id=?",use(deviceId),into(device),now;
        }
    } catch (Poco::Exception &e) {
        LOGW << "exception : " << e.what();
    }
    return device;
}

std::vector<TuogunProductDevice> TuogunProductDeviceManager::getAllTuogunProductDevice()
{
    std::vector<TuogunProductDevice> ver_device;
    try {
        if (MysqlSession::Instance()->session()) {
            Statement query(*MysqlSession::Instance()->session());
            query << " SELECT * FROM tuogun_product_device",into(ver_device),now;

            for (auto device : ver_device)
                printf(device);
        }
    } catch (Poco::Exception &e) {
        LOGW << "exception : " << e.what();
    }
    return ver_device;
}
